/*
 * Copyright 2021-2022 Open Kunlun Technology <https://www.openkunlun.io>
 */

package io.openkunlun.scalarpc.codegen.model

import scala.collection.immutable
import scala.meta._

/**
 * @author kostas.kougios
 *         Date: 12/10/17
 */
trait MetaEx
object MetaEx {

  trait Contains {
    def meta: MetaEx
  }

  trait ContainsMods[T] {
    def meta: MetaEx with Mods
    def mods: ModsEx = ModsEx(meta.mods)
    def withMods(mods: ModsEx): T
    def isPrivate: Boolean = mods.isPrivate
    def isProtected: Boolean = mods.isProtected
    def isPublic: Boolean = mods.isPublic
    def isOverrides: Boolean = mods.isOverrides
    def isVal: Boolean = mods.isVal
    def isCase: Boolean = mods.isCase
  }

  trait ContainsTypeParams[T] {
    def meta: MetaEx with TypeParams
    def typeParams: immutable.Seq[TypeParamEx] = meta.tparams.map(TypeParamEx.apply)
    def withTypeParams(params: Seq[TypeParamEx]): T
  }

  trait TypeParams {
    def tparams: Seq[scala.meta.Type.Param]
  }

  trait Template {
    def template: scala.meta.Template
  }

  trait Mods {

    def mods: Seq[Mod]
    def annotations: Seq[AnnotEx] = mods.collect {
      case mod"@$annot" => AnnotEx(AnnotEx.Meta(annot.init.tpe, annot.init.name, annot.init.argss.map(_.toSeq)))
    }

    def isPrivate: Boolean = mods.collect {
      case mod"private[$_]" => true
    }.nonEmpty

    def isProtected: Boolean = mods.collect {
      case mod"protected[$_]" => true
    }.nonEmpty

    def isPublic: Boolean = !isPrivate && !isProtected

    def isOverrides: Boolean = mods.collect {
      case mod"override" => true
    }.nonEmpty

    def isVal: Boolean = mods.exists {
      case _: Mod.ValParam => true
      case _               => false
    }

    def isCase: Boolean = mods.exists {
      case _: Mod.Case => true
      case _           => false
    }
  }
}